package edu.npu.cv.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.thymeleaf.spring5.context.webmvc.SpringWebMvcThymeleafRequestContext;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

/**
 * LogAspect  用于日志记录
 */

@Component
@Aspect
//@Order(1)
@Slf4j
public class LogAspect {



    private SpringWebMvcThymeleafRequestContext HttpContextUtil;
    private Object IPUtil;


    //匹配加了@log注解的方法    就是说在何处进行切面
    @Pointcut("execution(* edu.npu.cv..controller..*(..))")
    public void webLog() {
    }

    @Around("webLog()")
    public Object around(ProceedingJoinPoint pJoinPoint) throws Throwable {
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//        HttpServletRequest request = attributes.getRequest();
//
//        Class<?> aClass = pJoinPoint.getTarget().getClass();
//
//        String name = pJoinPoint.getSignature().getName();
//        Class<?>[] parameterTypes = ((MethodSignature) pJoinPoint.getSignature()).getParameterTypes();
//        Method method = aClass.getMethod(name, parameterTypes);//通过反射获得该方法
//
//        Log remarks = method.getAnnotation(Log.class);
//
//        //执行原方法
        //Object result = pJoinPoint.proceed();
          Object result = null;
          long beginTime = System.currentTimeMillis();

          try{
              //log.info("环绕通知中的前置");
              //执行原方法
              result = pJoinPoint.proceed();
              long endTime = System.currentTimeMillis();
//              //将日志写入数据库
              insertLog(pJoinPoint,endTime-beginTime);
          }catch(Throwable e){
              //System.out.println("环绕通知中的异常");
              //log.error("环绕通知中的异常");
          }

        return result;
    }


//    @Before("webLog()")
//    public void deBefore(JoinPoint joinPoint) throws Throwable {
//        // 接收到请求，记录请求内容
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//        HttpServletRequest request = attributes.getRequest();
//        // 记录下请求内容
//        log.info("ARGS: " + Arrays.toString(joinPoint.getArgs()) + "\n url: " + request.getRequestURL().toString() + "\n method: " + request.getMethod() + "\n ip: " + request.getRemoteAddr() + "\n ClassName.method: " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
//    }
//
//    @AfterReturning(returning = "ret", pointcut = "webLog()")
//    public void doAfterReturning(Object ret) throws Throwable {
//        // 处理完请求，返回内容
//        log.info("方法的返回值 : " + ret);
//    }
//
//    //后置异常通知
//    @AfterThrowing("webLog()")
//    public void methodThrows(JoinPoint jp) {
//        log.info("方法异常时执行.....");
//    }

    //后置最终通知,final增强，不管是抛出异常或者正常退出都会执行
    @After("webLog()")
    public void after(JoinPoint jp) {
        //log.info("请求执行完毕......");
    }

    //将日志插入到数据库的方法
    public void insertLog(ProceedingJoinPoint point,long time){
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
//        String token = point.getArgs()[1].toString().;
//        String ip = JWTUtils.parseToken(token, "ip");
        //System.out.println("token:"+ point.getArgs()[1]);
        //String token = point.getArgs()[1].toString();

        //获取操作用户信息
//        String username = JWTUtils.parseToken(token, "username");
//        User user = userService.selectByUsername(username);
        ServletRequestAttributes attr = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
        System.out.println(attr);
        HttpSession session=attr.getRequest().getSession(true);
        System.out.println(session);
        String nickName = session.getAttribute("nickName").toString();
        System.out.println(nickName);

        //获取IP
        HttpServletRequest httpServletRequest =
                ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        //反向代理不能用getRemoteAddr();
        String ip = httpServletRequest.getRemoteAddr();

//        History history = new History();
//
//        Log userAction = method.getAnnotation(Log.class);
//        if (userAction !=null){
//            //注解上的描述
//            history.setArgs(userAction.value());
//        }

        //请求的类名
        String className = point.getTarget().getClass().getSimpleName();
        //请求的方法名
        String methodName = signature.getName();
        //请求的方法参数值
        String args = Arrays.toString(point.getArgs());

//        int user_id = user.getId();
        /**
         *  id,method,args,insertTime,ret(类名)，ip
         */
        //log.info("方法执行后");
        log.info("用户:"+nickName+";IP:"+ip+";类名"+className+";方法名"+methodName+"\r\n;参数值"+args+"时间"+new Date());
//        history.setAdminId(user_id);
//        history.setMethod(methodName);
//        history.setArgs(args);
//        history.setInsertTime(new Date());
//        history.setRet(className);
//        history.setIp(ip);
//        historyService.insert(history);



    }

}
